// 布尔类型
let bool: boolean = true
let bool2: boolean
bool2 = false

// 不能将类型“123”分配给类型“boolean”
// bool = 123

// 数值类型
let num1: number = 123
num1 = 0b1111011
num1 = 0o173
num1 = 0x7b

// 字符串类型
let str: string = "abc"
str = `
    <div>
        <h2>数值是 ${num1}</h2>
    </div>
`
console.log(str)

// 数组类型

// 写法 1
const arr: number[] = [1, 2, 3]
console.log(arr)

// 写法 2 
const arr2: Array<number> = [4, 5, 6]
console.log(arr2)

// 写法 3 指定数组中的类型既可以是 string 也可以是 number
const arr3: (string | number)[] = [ 7, "Hello", 8, "world" ]
console.log(arr3)

// 元组类型 - 数组的拓展，与数组区别  - 固定长度  - 固定位置的类型
const tuple: [string, number, boolean] = ["hello", 2, true]
console.log(tuple)

// 枚举类型
// 默认下标从 0 开始
enum Roles {
    SUMPER_ADMIN,
    ADMIN,
    USER
}
console.log(Roles)
console.log(Roles.ADMIN)

// 可以指定开始下标
enum State {
    ONLINE = 1,
    OFFLINE,
    LEAVE = 5,
    HIDE
}
console.log(State)

// any 任何类型
let value: any
value = 1
value = false
value = "hello"

const arr4: any[] = [1, false, 'Hello']
console.log(arr4)

// void 类型 什么类型都不是
// 通常用于指定函数没有 return 语句时的类型
// 如果函数没有return 语句，默认返回 undefined
const consoleText = (text: string): void => console.log(text)
consoleText("hello void")

// 因此，void 类型的变量只能赋值为 undefined 
let v: void
v = undefined
// 如果 tsconfig.json 配置文件配置 "strictNullChecks": false, 或者 "strict": false,  可以赋值为 null
// v = null 

// null 和 undefined
let udf: undefined
udf = undefined

let nul: null
nul = null

// 非严格模式下，null 和 undefined 是其他类型的子类型，可以把这两个值赋值给 任意类型的值

// never 类型, throw Error() 返回值类型为 never
// 非严格模式下，never 类型的值 可以赋值给其他子类型
const errorFunc = (message: string): never => {
    throw new Error(message)
}

// 死循环的返回值类型为 never
const infiniteFunc = (): never => {
    while(true) {}
}

// let neverVariable: never = (() => {
//     while(true) {}
// })()

// neverVariable = 123

// object 类型
const obj = {
    name: 'lison'
}

const obj2 = obj
obj2.name = "L"
console.log(obj)

function getObject(obj: object): void {
    console.log(obj)
}

getObject(obj)

// 类型断言
// 两种方式 (<string>target) 或者 (target as string)
// 如果 使用 jsx 语法，则只能使用一种方式 (target as string), 因为 <> 在 jsx 中是语法
const getLength = (target: string|number): number => {
    if ((<string>target).length || (target as string).length === 0) {
        return (<string>target).length
    } else {
        return target.toString().length;
    }
}